#include <jni.h>
#include <stdio.h>
#include "InstanceFieldAccess.h"
/*
Get/SetObjectField
Get/SetIntField
Set/SetFloatField
*/
JNIEXPORT void JNICALL Java_InstanceFieldAccess_accessField (JNIEnv *env, jobject obj)
{
#if 0	
	jfieldID fid; /* store the field ID */
	jstring jstr;
	const char *str;

	/* Get a reference to obj’s class */
	jclass cls = (*env)->GetObjectClass(env, obj);

	printf("In C:\n");

	/* Look for the instance field s in cls */
	fid = (*env)->GetFieldID(env, cls, "s", "Ljava/lang/String;");
	if (fid == NULL) {
		return; /* failed to find the field */
	}

	/* Read the instance field s */
	jstr = (*env)->GetObjectField(env, obj, fid);
	str = (*env)->GetStringUTFChars(env, jstr, NULL);
	if (str == NULL ) {
		return;/* out of memory */
	}

	printf("  c.s = \"%s\"\n", str);
	(*env)->ReleaseStringUTFChars(env, jstr, str);

	/* Create a new string and overwrite the instance field */
	jstr = (*env)->NewStringUTF(env, "123");
	if (jstr == NULL) {
		return;/* out of memory */
	}
	(*env)->SetObjectField(env, obj, fid, jstr);
#else
	/*
	Obtaining field and method IDs requires symbolic lookups based 
	on the name and descriptor of the field or method. Symbolic lookups 
	are relatively expensive.To cache them is a better way.
	*/
	static jfieldID fid_s = NULL; /* cached field ID for s */
	jclass cls = (*env)->GetObjectClass(env, obj);
	jstring jstr;
	const  char *str;

	if (fid_s == NULL) {
		printf("fid_s init\n");
		fid_s = (*env)->GetFieldID(env, cls, "s", "Ljava/lang/String;");
		if  (fid_s == NULL) {
			return; /* exception already thrown */
		}
	} else {
		printf("fid_s has been cached\n");
	}
	printf("In C:\n");
	jstr = (*env)->GetObjectField(env, obj, fid_s);
	str = (*env)->GetStringUTFChars(env, jstr, NULL);
	if (str == NULL) {
		return; /* out of memory */
	}
	printf("  c.s = \"%s\"\n", str);
	(*env)->ReleaseStringUTFChars(env, jstr, str);
	jstr = (*env)->NewStringUTF(env, "123");
	if (jstr == NULL) {
		return; /* out of memory */
	}
	(*env)->SetObjectField(env, obj, fid_s, jstr);	
#endif	
}